from django.shortcuts import render,get_object_or_404, redirect
from accounts.models import Instance, UserAttributes, UserInstance
from django.views.decorators.cache import cache_page
from projsettings.settings import app_settings
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import AdminPasswordChangeForm
from django.contrib.auth.models import Group, User
from django.core.paginator import Paginator
from django.utils.translation import gettext_lazy as _
from logs.models import Logs
from computes.models import Compute
from libvirtmgr.hostdetails import wvmHostDetails
from libvirtmgr.storage import wvmStorages
from instances.models import Instance
from . import forms
import subprocess
from .decorators import superuser_only
from cloudlte import settings as basesetings
from decimal import Decimal,ROUND_HALF_UP
from django.core.cache import cache
# Create your views here.

LogTag = '------Debug------'

# @cache_page(60 * 15)
def page_index(request):
    # userinfo=get_object_or_404(User, pk=request.user.pk)
    dashboard_data=cache.get('dashboard')
    if not dashboard_data:
        compute_info=Compute.objects.all()
        # 计算节点总数量
        
        comp_count=compute_info.count()
        connection_count=0
        for sub_comp in compute_info:
            if len(sub_comp.hostname)==0:
                sub_comp.hostname="127.0.0.1"
            if is_connection(sub_comp.hostname):
                connection_count=connection_count+1
        # 计算节点在线数量
        comp_online=connection_count
        # 计算节点离线数量
        comp_offline = comp_count-comp_online
        
        # 云主机数量
        if request.user.is_superuser or request.user.has_perm("instances.view_instances"):
            instances = Instance.objects.all().prefetch_related("userinstance_set")
        else:
            instances = Instance.objects.filter(
                userinstance__user=request.user
            ).prefetch_related("userinstance_set")

        inst_count = instances.count()
        
        # 开机（激活）
        instance_acitvecount=0
        # 关机
        instance_closecount=0
        # 挂起
        instance_pausecount=0
        cpu_usage = 0
        mem_usage = 0
        blk_usage = 0
        for sub in instances:
            if sub.proxy.instance.info()[0]==1:
                instance_acitvecount=instance_acitvecount+1
            if sub.proxy.instance.info()[0]==3:
                instance_pausecount=instance_pausecount+1
            if sub.proxy.instance.info()[0]==5:
                instance_closecount=instance_closecount+1
            cpu_usage = cpu_usage+sub.proxy.instance.info()[3]
            mem_usage = mem_usage+sub.proxy.instance.info()[2]
            device_info=sub.proxy.get_disk_devices()
            for sub_blk_usage in device_info:
                blk_usage = blk_usage+sub_blk_usage['size']
            if device_info:
                device_info[0]['size']=device_info[0]['size']/1024/1024/1024
                
        # 资源池CPU总量
        vcpu_count=0
        # 资源池内存总量
        vmem_count=0
        # 资源池磁盘总量
        vdsk_count=0
        
        for compute in compute_info:
            instances_conn = wvmHostDetails(
            compute.hostname,
            compute.login,
            compute.password,
            compute.type,
            )
            host_info=instances_conn.get_node_info()
            vcpu_count=vcpu_count+host_info[3]
            vmem_count=vmem_count+host_info[2]
            vdsk_count=vdsk_count+host_info[2]
            storage_conn=wvmStorages(
                compute.hostname, compute.login, compute.password, compute.type
            )
            storage_info=storage_conn.get_storages_info()
            for storage in storage_info:
                vdsk_count=vdsk_count+storage['size']
        cpu_usage_display=round(cpu_usage,2)
        mem_usage_display=round(mem_usage/1024/1024,2)
        vmem_count_display=round(vmem_count/1024/1024/1024,2)
        vdsk_count_display=round(vdsk_count/1024/1024/1024,2)
        blk_usage_display = round(blk_usage/1024/1024/1024,2)
        
        vcpu_count=1 if vcpu_count==0 else vcpu_count
        vmem_count=1 if vmem_count==0 else vmem_count
        vdsk_count=1 if vdsk_count==0 else vdsk_count
        
        cpu_perc=str(round_dec(round(cpu_usage/vcpu_count,4)*100,2))+'%'
        mem_perc=str(round_dec(round((mem_usage*1024)/vmem_count,4)*100,2))+'%'
        disk_perc=str(round_dec(round(blk_usage/vdsk_count,4)*100,2))+'%'
    else:
        comp_count=dashboard_data['comp_count']
        comp_online=dashboard_data['comp_online']
        comp_offline=dashboard_data['comp_offline']
        inst_count=dashboard_data['inst_count']
        instance_acitvecount=dashboard_data['instance_acitvecount']
        instance_closecount=dashboard_data['instance_closecount']
        instance_pausecount=dashboard_data['instance_pausecount']
        cpu_usage_display=dashboard_data['cpu_usage_display']
        mem_usage_display=dashboard_data['mem_usage_display']
        vmem_count_display=dashboard_data['vmem_count_display']
        vdsk_count_display=dashboard_data['vdsk_count_display']
        blk_usage_display = dashboard_data['blk_usage_display']
        cpu_perc=dashboard_data['cpu_perc']
        mem_perc=dashboard_data['mem_perc']
        disk_perc=dashboard_data['disk_perc']
        instances=dashboard_data['instances']
        
        
    return render(
        request,
        'admin/index.html',
        locals()
    )

def round_dec(n,d):
  s = '0.' + '0' * d
  return Decimal(str(n)).quantize(Decimal(s),ROUND_HALF_UP)

@superuser_only
def group_list(request):
    groups = Group.objects.all()
    return render(
        request,
        "admin/group_list.html",
        {
            "groups": groups,
        },
    )


@superuser_only
def group_create(request):
    form = forms.GroupForm(request.POST or None)
    if form.is_valid():
        form.save()
        return redirect("admin:group_list")

    return render(
        request,
        "admin/group_form.html",
        {
            "form": form,
            "title": _("Create Group"),
        },
    )


@superuser_only
def group_update(request, pk):
    group = get_object_or_404(Group, pk=pk)
    form = forms.GroupForm(request.POST or None, instance=group)
    if form.is_valid():
        form.save()
        return redirect("admin:group_list")

    return render(
        request,
        "admin/group_form.html",
        {
            "form": form,
            "title": _("Update Group"),
        },
    )


@superuser_only
def group_delete(request, pk):
    group = get_object_or_404(Group, pk=pk)
    if request.method == "POST":
        group.delete()
        return redirect("admin:group_list")

    return render(
        request,
        "admin/confirm_delete.html",
        {"object": group},
    )


@superuser_only
def user_list(request):
    users = User.objects.all()
    return render(
        request,
        "admin/user_list.html",
        {
            "users": users,
            "title": _("Users"),
        },
    )


@superuser_only
def user_create(request):
    user_form = forms.UserCreateForm(request.POST or None)
    attributes_form = forms.UserAttributesForm(request.POST or None)
    if user_form.is_valid() and attributes_form.is_valid():
        user = user_form.save()
        password = user_form.cleaned_data["password"]
        user.set_password(password)
        user.save()
        attributes = attributes_form.save(commit=False)
        attributes.user = user
        attributes.save()
        add_default_instances(user)
        return redirect("admin:user_list")

    return render(
        request,
        "admin/user_form.html",
        {
            "user_form": user_form,
            "attributes_form": attributes_form,
            "title": _("Create User"),
        },
    )


@superuser_only
def user_update(request, pk):
    user = get_object_or_404(User, pk=pk)
    attributes = UserAttributes.objects.get(user=user)
    user_form = forms.UserForm(request.POST or None, instance=user)
    attributes_form = forms.UserAttributesForm(
        request.POST or None, instance=attributes
    )
    if user_form.is_valid() and attributes_form.is_valid():
        user_form.save()
        attributes_form.save()
        next = request.GET.get("next")
        return redirect(next or "admin:user_list")

    return render(
        request,
        "admin/user_form.html",
        {
            "user_form": user_form,
            "attributes_form": attributes_form,
            "title": _("Update User"),
        },
    )


@superuser_only
def user_update_password(request, pk):
    user = get_object_or_404(User, pk=pk)
    if request.method == "POST":
        form = AdminPasswordChangeForm(user, request.POST)
        if form.is_valid():
            user = form.save()
            update_session_auth_hash(request, user)  # Important!
            messages.success(
                request, _("Password changed for %(user)s") % {"user": user.username}
            )
            return redirect("admin:user_list")
        else:
            messages.error(request, _("Wrong Data Provided"))
    else:
        form = AdminPasswordChangeForm(user)

    return render(
        request,
        "accounts/change_password_form.html",
        {
            "form": form,
            "user": user.username,
        },
    )


@superuser_only
def user_delete(request, pk):
    user = get_object_or_404(User, pk=pk)
    if request.method == "POST":
        user.delete()
        return redirect("admin:user_list")

    return render(
        request,
        "admin/confirm_delete.html",
        {"object": user},
    )


@superuser_only
def user_block(request, pk):
    user: User = get_object_or_404(User, pk=pk)
    user.is_active = False
    user.save()
    return redirect("admin:user_list")


@superuser_only
def user_unblock(request, pk):
    user: User = get_object_or_404(User, pk=pk)
    user.is_active = True
    user.save()
    return redirect("admin:user_list")


@superuser_only
def logs(request):
    l = Logs.objects.order_by("-date")
    paginator = Paginator(l, int(app_settings.LOGS_PER_PAGE))
    page = request.GET.get("page", 1)
    logs = paginator.page(page)
    return render(request, "admin/logs.html", {"logs": logs})


def add_default_instances(user):
    """
    Adds instances listed in NEW_USER_DEFAULT_INSTANCES to user
    """
    existing_instances = UserInstance.objects.filter(user=user)
    if not existing_instances:
        for instance_name in settings.NEW_USER_DEFAULT_INSTANCES:
            instance = Instance.objects.get(name=instance_name)
            user_instance = UserInstance(user=user, instance=instance)
            user_instance.save()


def is_connection(host):
    result = subprocess.run(
        ['ping', '-c', '3', '-W', '5', host],
        capture_output=True,
        encoding='utf8'
    )
    if result.returncode == 0:
        return True
    else:
        return False